package com.gugee.common.web.system.user.service;

import com.gugee.common.web.util.jwt.JwtUser;
import com.gugee.common.web.util.jwt.JwtUtil;
import com.gugee.common.web.system.product.model.Product;
import com.gugee.common.web.system.product.repository.ProductRepository;
import com.gugee.common.web.system.product.service.ProductService;
import com.gugee.common.web.system.user.dto.AdsRecord;
import com.gugee.common.web.system.user.dto.UserReceiveDto;
import com.gugee.common.web.system.user.dto.UserReturnDto;
import com.gugee.common.web.system.user.model.User;
import com.gugee.common.web.system.user.model.UserRole;
import com.gugee.common.web.system.user.model.UserToken;
import com.gugee.common.web.system.user.repository.AdsRecordRepository;
import com.gugee.common.web.system.user.repository.UserRepository;
import com.gugee.common.web.system.user.repository.UserRoleRepository;
import com.gugee.common.web.system.user.repository.UserTokenRepository;
import com.xiguaji.boot.toolkit.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

@Service
@Slf4j
public class UserService {

    @Autowired
    UserRepository userRepository;
    @Autowired
    UserTokenRepository userTokenRepository;
    @Autowired
    JwtUtil jwtUtil;
    @Autowired
    UserReceiveDto.UserMapper userReceiveMapper;
    @Autowired
    UserReturnDto.UserMapper userReturnMapper;
    @Autowired
    UserRoleRepository userRoleRepository;
    @Autowired
    AdsRecordRepository adsRecordRepository;
    @Autowired
    ProductRepository productRepository;
    @Autowired
    ProductService productService;


    public String login(User user){
        JwtUser jwtUser = new JwtUser();
        jwtUser.setUser(user);
        String token = jwtUtil.generaToken(jwtUser);
        UserToken userToken = getUserToken(user.getId());

        if(null == userToken){
            userToken = new UserToken();
        }
        userToken.setUserId(user.getId());
        userToken.setAutoLogin(false);
        userToken.setIp(HttpUtil.getIp());
        userToken.setToken(token);
        userToken.setCreateBy("tiktok->UserService->login");
        userToken.setUpdateBy("tiktok->UserService->login");
        saveUserToken(userToken);
        return token;
    }

    public User getUserByEmailAndPassword(String email,String password){
        return userRepository.findUserByEmailAndPassword(email,password);
    }

    public Boolean validaToken(String token){
        UserToken userToken = userTokenRepository.findUserTokenByToken(token);

        if(null != userToken){
            return jwtUtil.validateToken(token);
        }
        log.debug("{}:不存在数据库中",token);
        return false;
    }

    public String tokenLogin(String token,Boolean autoLogin,String ip){
        UserToken userToken = userTokenRepository.findUserTokenByTokenAndAutoLoginAndIp(token,autoLogin,ip);

        if(null != userToken){
            JwtUser jwtUser = jwtUtil.getJwtUserByToken(token);

            if(null != jwtUser){
                User getUser =  (User) jwtUser.getUser();
                User user = userRepository.findUserByEmailAndPasswordAndActivation(getUser.getEmail(),getUser.getPassword(),true);

                if(null != user){
                    String newToken = jwtUtil.generaToken(jwtUser);
                    userToken.setToken(newToken);
                    userToken.setCreateBy("tiktok->UserService->tokenLogin");
                    userToken.setUpdateBy("tiktok->UserService->tokenLogin");
                    saveUserToken(userToken);
                    return newToken;
                }
            }
        }
        return null;
    }

    public void deleteAccount(long userId){
        userRepository.deleteById(userId);
    }

    public void saveUser(User user){
        userRepository.save(user);
    }

    public User getUserByEamil(String email){
        return userRepository.findUserByEmail(email);
    }

    public UserRole getUserRole(long userId, Date date){
        val userRoleOptional = userRoleRepository.findTop1ByUserIdAndExpireTimeGreaterThanEqualOrderByRoleIdDesc(userId, date);
        return userRoleOptional.isPresent()?userRoleOptional.get():null;
    }

    public User getUserById(Long userId){
        val userOptional = userRepository.findById(userId);
        return userOptional.isPresent()?userOptional.get():null;
    }

    public UserReturnDto getUser(Long userId){
        User user = userRepository.findById(userId).get();
        UserReturnDto userReturnDto = userReturnMapper.mapper(user);
        List<UserRole> userRoles;

        if(user.getParentId() == 0){
            userRoles = userRoleRepository.findByUserIdOrderByExpireTimeDesc(userId);
        }else{
            userRoles = userRoleRepository.findByUserIdOrderByExpireTimeDesc(user.getParentId());
        }
        List<Product> products = productRepository.findByEnableAndTypeOrderByLevel(true,"version");
        val userToken = getUserToken(userReturnDto.getId());

        if(null != userToken){
            userReturnDto.setLastLoginTime(userToken.getUpdateTime());
        }
        if(!StringUtils.isEmpty(user.getPassword())){
            userReturnDto.setHavePassword(true);
        }
        if(userRoles.size() == 0){
            userReturnDto.setRoleId(products.get(0).getId());
            userReturnDto.setEdition(products.get(0).getName());
            userReturnDto.setHistoryRoleId(products.get(0).getId());
            userReturnDto.setHistoryEdition(products.get(0).getName());
        }else {

            AtomicReference<Product> curProduct = new AtomicReference<>();
            products.stream().forEach( x->{
                if(x.getId() == userRoles.get(0).getRoleId()){
                    curProduct.set(x);
                }
            });

            if(userRoles.get(0).getExpireTime().getTime() > new Date().getTime()){
                userReturnDto.setRoleId(curProduct.get().getId());
                userReturnDto.setEdition(curProduct.get().getName());
                userReturnDto.setHistoryRoleId(curProduct.get().getId());
                userReturnDto.setHistoryEdition(curProduct.get().getName());
                userReturnDto.setExpiredDate(userRoles.get(0).getExpireTime().getTime());
            }else {
                userReturnDto.setRoleId(products.get(0).getId());
                userReturnDto.setEdition(products.get(0).getName());
                userReturnDto.setHistoryRoleId(curProduct.get().getId());
                userReturnDto.setHistoryEdition(curProduct.get().getName());
                userReturnDto.setExpiredDate(userRoles.get(0).getExpireTime().getTime());
            }
        }
        userReturnDto.setDailyReports(productService.unlockedNumberByRole(userId,userReturnDto.getRoleId()));
        userReturnDto.setCreditsBalance(productService.unlockedNumberByReportStarter(userId));
        return userReturnDto;
    }

    public List<UserReturnDto> getUserList(Long userId){
        List<UserReturnDto> userReturnDtoList = new ArrayList<>();
        List<User> users = userRepository.getUserListByParentIdOrderByCreateTimeDesc(userId);
        users.forEach( u->{
            val userReturnDto = userReturnMapper.mapper(u);
            val userToken = getUserToken(userReturnDto.getId());

            if(null != userToken){
                userReturnDto.setLastLoginTime(userToken.getUpdateTime());
            }
            userReturnDtoList.add(userReturnDto);
        });
        return userReturnDtoList;
    }


    public void saveAdsRecord(AdsRecord adsRecord){
        adsRecordRepository.save(adsRecord);
    }

    public void saveUserToken(UserToken userToken){
        userTokenRepository.save(userToken);
    }

    public UserToken getUserToken(Long userId){
        return userTokenRepository.findUserTokenByUserId(userId);
    }

}
